package cn.shuibo.util;


import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 服务器端，安全类，包含各类加密和规则
 * @author K.
 *
 */
public class ServiceSafety {
	/**
	 * 字符编码
	 */
	private static final String ENCODE = "UTF-8";

	private static MessageDigest sha1MD;
	/**
	 * SHA加密算法
	 */
	private static String SHA(String word,String type){
		if(null == sha1MD){
			try {
				sha1MD = MessageDigest.getInstance(type);
			} catch (NoSuchAlgorithmException e) {
				return null;
			}
		}
		try {
			byte[] king=word.getBytes(ENCODE);
			sha1MD.update(king, 0, king.length);
		} catch (UnsupportedEncodingException e) {
			sha1MD.update(word.getBytes(), 0, word.length());
		}
		return toHexString(sha1MD.digest());
	}
	/**
	 *
	 */
	private static String toHexString(byte [] hashs){
		StringBuffer sBuffer = new StringBuffer();
		for(byte hash : hashs){
			sBuffer.append(Integer.toString(( hash & 0xFF ) + 0x100, 16).substring( 1 ));
		}
		return sBuffer.toString();
	}
	/**
	 * sha_1
	 */
	public static String Sha_1(String word){
		return SHA(word,"SHA-1");
	}
	/**
	 * sha_512
	 */
	public static String Sha_512(String word){
		return SHA(word,"SHA-512");
	}
	/**
	 * hmac-sha1 加密模式
	 */
	public static String HmacSha1(String data, String key) {
		byte[] byteHMAC = null;
		try {
			Mac mac = Mac.getInstance("HmacSHA1");
			SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
			mac.init(spec);
			byteHMAC = mac.doFinal(data.getBytes());
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException ignore) {
		}
		//String oauth = new BASE64Encoder().encode(byteHMAC);
		String oauth = Base64.getEncoder().encodeToString(byteHMAC);
		return oauth;
	}
	/**
	 * 加密MD5
	 */
	public static String Md5(String plainText) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(plainText.getBytes("UTF-8"));
			byte b[] = md.digest();
			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			return buf.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}
	/**
	 *
	 */
	private static String toString(String[] Elements) {
		StringBuffer Atomic=new StringBuffer();
		for(int i=0;i<Elements.length;i++){
			Atomic.append(Elements[i]);
		}
		return Atomic.toString();
	}


	/**
	 * 位移加密
	 * @param s
	 * @param STR_AZ
	 * @return
	 */
	public static String encrypt(String s,String STR_AZ) {
		StringBuffer ss = new StringBuffer();
		int k=s.length();//加密算法位移量
		for (int i = 0; i < s.length(); i++) {
			char tempi = s.charAt(i);
			int index=0;
			for (int j = 0; j < STR_AZ.length(); j++) {
				//大于最大位后，从初的A取。形成循环
				if (tempi == STR_AZ.charAt(j)) {
					index=j+k;
					if (index/ STR_AZ.length()>=1){
						index=index%STR_AZ.length();
					}
					ss.append(STR_AZ.charAt(index));
				}
			}
			k--;
		}
		return ss.toString();
	}

	/**
	 * 位移解密
	 * @param s
	 * @param STR_AZ
	 * @return
	 */
	public static String decrypt(String s,String STR_AZ){
		StringBuffer ssde = new StringBuffer();
		int k=s.length();//加密算法位移量
		for (int i = 0; i < s.length(); i++) {
			char tempi = s.charAt(i);
			int index=0;
			for (int j = 0; j < STR_AZ.length(); j++) {
				if (tempi == STR_AZ.charAt(j)) {
					//小于最小位后，从最大的Z取，形成循环
					index=j-k;
					if((index/STR_AZ.length())!=0){
						index=index%STR_AZ.length();
					}
					if (index < 0 ){
						index=STR_AZ.length()+index;
					}
					ssde.append(STR_AZ.charAt(index));
				}
			}
			k--;
		}
		return ssde.toString();
	}

	/**
	 * 获取待加密字符串
	 * @return
	 */
	public static String getEncryptedWord(String... word){
		StringBuffer encrypted=new StringBuffer();
		List<String> strs=Arrays.asList(word);
		Collections.sort(strs, new Comparator() {
			@Override
			public int compare(Object o1, Object o2) {
				String str1=(String) o1;
				String str2=(String) o2;
				if (str1.compareToIgnoreCase(str2)<0){
					return -1;
				}
				return 1;
			}
		});
		for(String index:strs){
			encrypted.append(index);
		}
		return encrypted.toString();
	}
}
